package com.zsc.oj.controller;

import cn.hutool.core.net.multipart.UploadFile;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.zsc.oj.common.BaseResponse;
import com.zsc.oj.common.ErrorCode;
import com.zsc.oj.common.ResultUtils;
import com.zsc.oj.constant.CommonConstant;
import com.zsc.oj.exception.BusinessException;
import com.zsc.oj.mapper.QuestionSubmitMapper;
import com.zsc.oj.model.dto.file.UploadFileRequest;
import com.zsc.oj.model.dto.team.*;
import com.zsc.oj.model.entity.Team;
import com.zsc.oj.model.entity.User;
import com.zsc.oj.model.entity.UserTeam;
import com.zsc.oj.model.enums.FileUploadBizEnum;
import com.zsc.oj.model.vo.TeamRankVO;
import com.zsc.oj.model.vo.UserVO;
import com.zsc.oj.service.TeamService;
import com.zsc.oj.service.UserService;
import com.zsc.oj.service.UserTeamService;
import com.zsc.oj.utils.SqlUtils;
import com.zsc.oj.utils.UploadFileUtils;
import com.zsc.oj.utils.ValidFileUtils;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/team")
@Slf4j
public class TeamController {

    @Resource
    private TeamService teamService;

    @Resource
    private UserService userService;

    @Resource
    private UserTeamService userTeamService;

    @Resource
    private QuestionSubmitMapper questionSubmitMapper;

    /**
     * 创建（添加）队伍
     *
     * @param teamAddRequest
     * @return
     */
    @PostMapping("/add")
    public BaseResponse<Long> addTeam(@RequestBody TeamAddRequest teamAddRequest, HttpServletRequest request) {
        if (teamAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        Team team = new Team();

        //将使用apache工具将teamAddRequest传给team
        try {
            BeanUtils.copyProperties(team,teamAddRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //调用业务逻辑层的方法进行校验与插入
        long teamId = teamService.createTeam(team, loginUser);

        //因为要返回的是添加成功数目，这里mybatis添加成功后会在属性上生成一个id
        return ResultUtils.success(teamId);
    }


    /**
     * 更新队伍
     *
     * @param teamUpdateRequest
     * @return
     */
    @PostMapping("/update")
    public BaseResponse<Boolean> update(@RequestBody TeamUpdateRequest teamUpdateRequest, HttpServletRequest request) {
        if (teamUpdateRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.updateTeam(teamUpdateRequest, loginUser);
        if (!result) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        return ResultUtils.success(result);
    }

    /**
     * 根据id查询队伍
     *
     * @param id
     * @return
     */
    @GetMapping("/get")
    public BaseResponse<Team> getTeamById(Long id) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = teamService.getById(id);
        if (team == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        return ResultUtils.success(team);
    }

    /**
     * 查询所有队伍
     *
     * @param teamQuery：请求参数包装类
     * @return
     */
//    @GetMapping("/list")
//    public BaseResponse<List<TeamUserVO>> getTeamList(TeamQueryRequest teamQuery, HttpServletRequest request) {
//        if (teamQuery == null) {
//            throw new BusinessException(ErrorCode.PARAMS_ERROR);
//        }
//
//        User loginUser = userService.getLoginUser(request);
//        boolean isAdmin = userService.isAdmin(request);
//        //1、查询队伍列表
//        List<TeamUserVO> teamUserVOList = teamService.listTeam(teamQuery,isAdmin);
//
//        if(teamUserVOList.isEmpty()){
//            return ResultUtils.success(teamUserVOList);
//        }
//
//        //下面这段逻辑是给前端退出按钮展示给已加入队伍的用户看的
//
//        //获取到teamUserVOList的所有id并形成一个列表
//        List<Long> teamIdList = teamUserVOList.stream().map(TeamUserVO::getId).collect(Collectors.toList());
//
//        //2、判断当前用户是否已加入队伍
//        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
//
//
//        userTeamQueryWrapper.eq("userId",loginUser.getId());
//        userTeamQueryWrapper.in("teamId",teamIdList);
//        //当前用户已加入队伍的列表
//        List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
//
//        //获取当前用户已加入队伍的队伍id
//        Set<Long> hasJoinTeamIdSet = userTeamList.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
//        teamUserVOList.forEach(team ->{
//            boolean hasJoin = hasJoinTeamIdSet.contains(team.getId());
//            team.setHasJoin(hasJoin);
//        });
//
//        //3、查询加入队伍的用户人数
//        QueryWrapper<UserTeam> userTeamJoinQueryWrapper = new QueryWrapper<>();
//        userTeamJoinQueryWrapper.in("teamId",teamIdList);
//        List<UserTeam> userTeamLists = userTeamService.list(userTeamJoinQueryWrapper);
//        Map<Long, List<UserTeam>> joinTeamMap = userTeamLists.stream().collect(Collectors.groupingBy(UserTeam::getTeamId));
//        teamUserVOList.forEach(team ->{
//            team.setJoinNum(joinTeamMap.getOrDefault(team.getId(),new ArrayList<>()).size());
//        });
//
//
//        return ResultUtils.success(teamUserVOList);
//    }


    /**
     * 分页查询队伍
     *
     * @param teamQueryRequest：请求参数包装类
     * @return
     */
    @GetMapping("/list/page")
    public BaseResponse<Page<TeamUserVO>> getTeamListPage(TeamQueryRequest teamQueryRequest, HttpServletRequest request) {
        if (teamQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        //team转化为teamQuery的操作，这里使用了apache的一个工具类进行转换
        Team team = new Team();
        try {
            BeanUtils.copyProperties(teamQueryRequest, team);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //使用teamService.list查询是发现接收的参数只能是team，所以要将team强转为teamQuery
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>(team);

        int current = teamQueryRequest.getCurrent();
        int pageSize = teamQueryRequest.getPageSize();
        Page<Team> page = new Page<>(current, pageSize);
        Page<Team> teamPage = teamService.page(page, queryWrapper);
        long total = teamPage.getTotal();
        Page<TeamUserVO> teamUserVOPage = new Page<>(current,pageSize,total);

//        List<TeamUserVO> teamUserVOList = userTeamService.getTeamUserVO(teamQueryRequest,request);

        User loginUser = userService.getLoginUser(request);
        boolean isAdmin = userService.isAdmin(request);
        //1、查询队伍列表
        List<TeamUserVO> teamUserVOList = teamService.listTeam(teamQueryRequest,isAdmin);

        if(teamUserVOList.isEmpty()){
            return ResultUtils.success(new Page<>());
        }

        //下面这段逻辑是给前端退出按钮展示给已加入队伍的用户看的

        //获取到teamUserVOList的所有id并形成一个列表
        List<Long> teamIdList = teamUserVOList.stream().map(TeamUserVO::getId).collect(Collectors.toList());

        //2、判断当前用户是否已加入队伍
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();


        userTeamQueryWrapper.eq("userId",loginUser.getId());
        userTeamQueryWrapper.in("teamId",teamIdList);
        //当前用户已加入队伍的列表
        List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);

        List<UserTeam> userTeams = userTeamService.list();
        //查询加入队伍的用户，组成一个map，如{teamId:["用户1","用户2"]}
        Map<Long, List<Long>> map = userTeams.stream().collect(Collectors.groupingBy(UserTeam::getTeamId, Collectors.mapping(UserTeam::getUserId, Collectors.toList())));

        //获取当前用户已加入队伍的队伍id
        Set<Long> hasJoinTeamIdSet = userTeamList.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
        teamUserVOList.forEach(teamUserVO ->{
            boolean hasJoin = hasJoinTeamIdSet.contains(teamUserVO.getId());
            teamUserVO.setHasJoin(hasJoin);
        });

        //3、查询加入队伍的用户人数
        QueryWrapper<UserTeam> userTeamJoinQueryWrapper = new QueryWrapper<>();
        userTeamJoinQueryWrapper.in("teamId",teamIdList);
        List<UserTeam> userTeamLists = userTeamService.list(userTeamJoinQueryWrapper);
        Map<Long, List<UserTeam>> joinTeamMap = userTeamLists.stream().collect(Collectors.groupingBy(UserTeam::getTeamId));
        teamUserVOList.forEach(teamUserVO ->{
            teamUserVO.setJoinNum(joinTeamMap.getOrDefault(teamUserVO.getId(),new ArrayList<>()).size());
        });

        //将加入队伍用户的信息返回出去
        for (TeamUserVO teamUserVO : teamUserVOList) {
            for (Map.Entry<Long, List<Long>> entry : map.entrySet()) {
                if(teamUserVO.getId().equals(entry.getKey())){
                    teamUserVO.setJoinUserList(entry.getValue().stream().map(e ->{
                        User user = userService.getById(e);
                        UserVO userVO = UserVO.objToVo(user);
                        return userVO;
                    }).collect(Collectors.toList()));
                }
            }
        }

        teamUserVOPage.setRecords(teamUserVOList);


        return ResultUtils.success(teamUserVOPage);
    }

    /**
     * 加入队伍
     * @param teamJoinRequest
     * @param request
     * @return
     */
    @PostMapping("/join")
    public BaseResponse<Boolean> joinTeam(@RequestBody TeamJoinRequest teamJoinRequest, HttpServletRequest request) {
        if (teamJoinRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.joinTeam(teamJoinRequest, loginUser);
        return ResultUtils.success(result);
    }

    /**
     * 用户退出队伍
     *
     * @param teamQuitRequest
     * @param request
     * @return
     */
    @PostMapping("/quit")
    public BaseResponse<Boolean> quitTeam(@RequestBody TeamQuitRequest teamQuitRequest, HttpServletRequest request) {
        if (teamQuitRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.quitTeam(teamQuitRequest, loginUser);
        return ResultUtils.success(result);
    }

    /**
     * 队长 / 管理员 可解散队伍
     *
     * @param teamQuitRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    public BaseResponse<Boolean> LeaderQuitTeam(@RequestBody TeamQuitRequest teamQuitRequest, HttpServletRequest request) {
        if (teamQuitRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        User loginUser = userService.getLoginUser(request);
        boolean result = teamService.leaderQuitTeam(teamQuitRequest, loginUser);
        return ResultUtils.success(result);
    }

    /**
     * 查询我创建的队伍（查询team表中userId字段）
     * @param teamQueryRequest
     * @param request
     * @return
     */
    @GetMapping("/list/my/create")
    public BaseResponse<List<TeamUserVO>> getMyCreateTeam(TeamQueryRequest teamQueryRequest, HttpServletRequest request) {
        if (teamQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        User loginUser = userService.getLoginUser(request);
        teamQueryRequest.setUserId(loginUser.getId());
        //这里设置管理员的权限为true，是因为我创建的队伍
        List<TeamUserVO> myTeamList = teamService.listMyCreateTeam(teamQueryRequest);
        return ResultUtils.success(myTeamList);
    }

    /**
     * 查询我加入的队伍
     * @param teamQueryRequest
     * @param request
     * @return
     */
    @GetMapping("/list/my/join")
    public BaseResponse<List<TeamUserVO>> getMyJoinTeam(TeamQueryRequest teamQueryRequest, HttpServletRequest request) {
        if (teamQueryRequest == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
        User loginUser = userService.getLoginUser(request);

        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId",loginUser.getId());
        List<UserTeam> userTeamList = userTeamService.list(queryWrapper);//查询出来关系表中当前登录用户对应的id列表

        //将userId与对应的teamId进行对应的分组
        //下面的这一行代码：userId和对用的teamId进行分组，teamId为key，userId为value，就行形成下面类似例子
        //比如：userId=1的用户加入了，队伍2，3，4。就会表示为：2 => 1，3 => 1，4 => 1
        Map<Long, List<UserTeam>> listMap = userTeamList.stream().collect(Collectors.groupingBy(UserTeam::getTeamId));
        List<Long> idList = new ArrayList<>(listMap.keySet());
        teamQueryRequest.setIdList(idList);

        //这里设置管理员的权限为true，是因为我创建的队伍
        List<TeamUserVO> myTeamList = teamService.listTeam(teamQueryRequest, true);
        return ResultUtils.success(myTeamList);

    }

    /**
     * 队伍排行榜
     * @param teamQueryRequest
     * @return
     */
    @GetMapping("/get_rank")
    public BaseResponse<Page<TeamRankVO>> getTeamRank(TeamQueryRequest teamQueryRequest){
        List<Team> teamList = teamService.list();
        List<Long> teamIdList = teamList.stream().map(Team::getId).collect(Collectors.toList());
        List<TeamRankVO> teamRankVOList = new ArrayList<>();

        if (teamQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        //team转化为teamQuery的操作，这里使用了apache的一个工具类进行转换
        Team team = new Team();
        try {
            BeanUtils.copyProperties(teamQueryRequest, team);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        int current = teamQueryRequest.getCurrent();
        int pageSize = teamQueryRequest.getPageSize();
        String sortField = teamQueryRequest.getSortField();
        String sortOrder = teamQueryRequest.getSortOrder();

        //使用teamService.list查询是发现接收的参数只能是team，所以要将team强转为teamQuery
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>(team);
        // 排序规则
//        queryWrapper.orderBy(SqlUtils.validSortField(sortField),
//                sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
//                sortField);


        //进行分页
        Page<Team> page = new Page<>(current, pageSize);
        Page<Team> teamPage = teamService.page(page, queryWrapper);
        long total = teamPage.getTotal();
        Page<TeamRankVO> teamRankVOPage = new Page<>(current,pageSize,total);

        for (Long teamId : teamIdList) {
            QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
            userTeamQueryWrapper.eq("teamId",teamId);
            List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
            int teamAcceptNum = 0;
            //获取到题目id对应的userId
            List<Long> userIds = userTeamList.stream().map(UserTeam::getUserId).collect(Collectors.toList());
            for (Long userId : userIds) {
                Integer userAcceptNum = questionSubmitMapper.getUserAccept(userId);
                teamAcceptNum += userAcceptNum;
            }
            TeamRankVO teamRankVO = new TeamRankVO();
            Team newTeam = teamService.getById(teamId);
            try {
                BeanUtils.copyProperties(teamRankVO,newTeam);
            } catch (Exception e) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            teamRankVO.setAcceptNum(teamAcceptNum);
            teamRankVOList.add(teamRankVO);
        }

        // 按照 acceptNum 字段降序排序列表
        teamRankVOList.sort(Comparator.comparing(TeamRankVO::getAcceptNum).reversed());

        teamRankVOPage.setRecords(teamRankVOList);
//        teamRankVOPage.addOrder("")

        return ResultUtils.success(teamRankVOPage);
    }


    /**
     * 上传队伍图标
     * @param multipartFile
     * @param uploadFileRequest
     * @return
     */
    @PostMapping("/upload")
    public BaseResponse<String> uploadTeamIcon(@RequestPart("file") MultipartFile multipartFile,
                                                UploadFileRequest uploadFileRequest,HttpServletRequest request){
        String biz = uploadFileRequest.getBiz();
        FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz);
        if (fileUploadBizEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 检验文件大小
        ValidFileUtils.validFile(multipartFile, fileUploadBizEnum);
        User loginUser = userService.getLoginUser(request);

        //文件上传
        String result = teamService.uploadUserAvatar(fileUploadBizEnum,multipartFile);

        return ResultUtils.success(result);
    }
}

